#include "StdAfx.h"
#include "DBWriter.h"

using namespace System;
using namespace System::Data;
using namespace System::IO;
using namespace System::Data::SqlClient;
using namespace System::Data::SqlTypes;
using namespace System::Xml;

DBWriter::DBWriter ()
{
	// Nothing here
}

void DBWriter::Connect (SqlCommand ^Command)
{
	array<String^>^ ConnectionString = File::ReadAllLines(L"ConfigIP.txt");
	Command->Connection = gcnew SqlConnection(ConnectionString[0]);
	Command->Connection->Open();
	Command->CommandTimeout = 600;
}

void DBWriter::Read (SqlCommand ^Command, int *N)
{
	SqlDataReader ^Reader;

	try
	{
		Reader = Command->ExecuteReader();

		if (Reader->Read())
		{
			*N = Reader->GetInt32(0);
		}
		else
		{
			*N = 0;
		}
	}
	catch(System::Exception ^Exception)
	{
		Reader->Close();
		throw(Exception);
	}

	Reader->Close();
}

void DBWriter::SaveClusters (int *FlightIDs, int FlightsNum, char *ClusteringType, int ClustersNum, char *Date, char *Comment,
	double **Labels, double *ClusterParams, int ParamsNum)
{
	// FlightIDs -- array of processed flight IDs
	// FlightsNum -- number of IDs
	// ClusteringType -- name of the clustering type
	// ClustersNum -- number of obtained clusters
	// Labels -- 2D array of cluster labels for each vector for each flight from FlightIDs
	// ClusterParams -- parameters of the clustering
	// ParamsNum -- length of ClusterParams (in doubles!)
	String ^RunDate = gcnew String(Date);
	String ^RunComment = gcnew String(Comment);
	String ^Type = gcnew String(ClusteringType);
	
	int ClusteringRunID;
	int *ClusterIDs = new int[ClustersNum];
	Int32 ^ClNum = ClustersNum;

	System::IO::StreamWriter ^Log = gcnew System::IO::StreamWriter("writerlog.txt", true);

	Log->WriteLine(System::DateTime::Now + " DBWriter::SaveClusters message.");
	Log->WriteLine(RunDate);
	Log->WriteLine(RunComment);
	Log->WriteLine(Type);
	Log->WriteLine("ClustersNum = {0}", ClustersNum);
	Log->WriteLine("FlightsNum = {0}", FlightsNum);
	for (int i = 0; i < FlightsNum; ++i)
	{
		Log->Write("{0} ", FlightIDs[i]);
	}
	Log->WriteLine("");
	
	Log->Close();

	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);

		// Saving current clustering run
		Command->CommandText = "EXECUTE SaveClusteringRun @Type = '" + Type + "', @ClustersNum = " + ClNum->ToString() +
			", @Date = '" + RunDate + "', @Comment = '" + RunComment + "'";
		Read(Command, &ClusteringRunID); // Getting it's ID

		Int32 ^ClustNum;
		Int32 ^ClustRunId = ClusteringRunID; // Adding clusters into cluster table
		for (int i = 0; i < ClustersNum; ++i)
		{
			ClustNum = i + 1;
			Command->CommandText = "EXECUTE SaveCluster @Number = " + ClustNum->ToString() + ", @ClusteringRunId = " +
				ClustRunId->ToString();
			Read(Command, &ClusterIDs[i]); // And getting their IDs.
		}

		// Inserting parameters
		array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(ClusterParams, ParamsNum); // Converting double array to byte array
		// Saving clustering params
		Command->CommandText = "EXECUTE NewClusterParam @RunIdParam, @ClusterDataParam";
		Command->Parameters->AddWithValue("@RunIdParam", ClusteringRunID);
		Command->Parameters->AddWithValue("@ClusterDataParam", ParamData);
		Command->ExecuteNonQuery();

		// Insert flight clusterings
		Command->Parameters->Clear();
		Command->CommandText = "EXECUTE NewFlightClustering @RunIDParam, @ProcFlightID";
		SqlParameter ^RunIDParam = Command->Parameters->Add("@RunIDParam", SqlDbType::Int); // ClusteringRunID
		SqlParameter ^ProcessedFlightID = Command->Parameters->Add("@ProcFlightID", SqlDbType::Int); // ProcessedFlightID
	
		RunIDParam->Value = ClusteringRunID; // It is the same for the whole loop
		Command->Prepare();
		for (int i = 0; i < FlightsNum; i++)
		{
			ProcessedFlightID->Value = FlightIDs[i];
			Command->ExecuteNonQuery();
		}

		// Delete (if exist) dublicates of current results
		//Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString();
		//Command->ExecuteNonQuery();

		for (int i = 0; i < FlightsNum; i++)
		{
			Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString() + ", " + Convert::ToString(FlightIDs[i]);
			Command->ExecuteNonQuery();
			InsertClusterLabels(FlightIDs[i], Labels[i], ClusterIDs); // Inserting labels into VectorCluster table
		}
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		delete[] ClusterIDs;
		throw(Exception);
	}
	
	Command->Connection->Close();
	delete[] ClusterIDs;
}

void DBWriter::SaveClusters (int *FlightIDs, int FlightsNum, char *ClusteringType, int ClustersNum, char *Date, char *Comment,
	double **Labels, double *ClusterParams, int ParamsNum, double *UsedParametersNames, int UsedParamsNum)
{
	// FlightIDs -- array of processed flight IDs
	// FlightsNum -- number of IDs
	// ClusteringType -- name of the clustering type
	// ClustersNum -- number of obtained clusters
	// Labels -- 2D array of cluster labels for each vector for each flight from FlightIDs
	// ClusterParams -- parameters of the clustering
	// ParamsNum -- length of ClusterParams (in doubles!)
	String ^RunDate = gcnew String(Date);
	String ^RunComment = gcnew String(Comment);
	String ^Type = gcnew String(ClusteringType);
	
	int ClusteringRunID;
	int *ClusterIDs = new int[ClustersNum];
	Int32 ^ClNum = ClustersNum;

	System::IO::StreamWriter ^Log = gcnew System::IO::StreamWriter("writerlog.txt", true);

	Log->WriteLine(System::DateTime::Now + " DBWriter::SaveClusters message.");
	Log->WriteLine(RunDate);
	Log->WriteLine(RunComment);
	Log->WriteLine(Type);
	Log->WriteLine("ClustersNum = {0}", ClustersNum);
	Log->WriteLine("FlightsNum = {0}", FlightsNum);
	for (int i = 0; i < FlightsNum; ++i)
	{
		Log->Write("{0} ", FlightIDs[i]);
	}
	Log->WriteLine("");
	
	Log->Close();

	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		array<System::Byte> ^UsedParametersNamesData = ConvertDoubleArrayToByteArray(UsedParametersNames, UsedParamsNum); // Converting double array to byte array

		Connect(Command);

		// Saving current clustering run
		Command->CommandText = "EXECUTE SaveClusteringRun @Type = '" + Type + "', @ClustersNum = " + ClNum->ToString() +
			", @Date = '" + RunDate + "', @Comment = '" + RunComment + "'";
		Read(Command, &ClusteringRunID); // Getting it's ID

		Int32 ^ClustNum;
		Int32 ^ClustRunId = ClusteringRunID; // Adding clusters into cluster table
		for (int i = 0; i < ClustersNum; ++i)
		{
			ClustNum = i + 1;
			Command->CommandText = "EXECUTE SaveCluster @Number = " + ClustNum->ToString() + ", @ClusteringRunId = " +
				ClustRunId->ToString();
			Read(Command, &ClusterIDs[i]); // And getting their IDs.
		}

		// Inserting parameters
		array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(ClusterParams, ParamsNum); // Converting double array to byte array
		// Saving clustering params
		Command->CommandText = "EXECUTE NewClusterParam @RunIdParam, @ClusterDataParam, @UsedParametersNames";
		Command->Parameters->AddWithValue("@RunIdParam", ClusteringRunID);
		Command->Parameters->AddWithValue("@ClusterDataParam", ParamData);
		Command->Parameters->AddWithValue("@UsedParametersNames", UsedParametersNamesData);
		Command->ExecuteNonQuery();

		// Insert flight clusterings
		Command->Parameters->Clear();
		Command->CommandText = "EXECUTE NewFlightClustering @RunIDParam, @ProcFlightID";
		SqlParameter ^RunIDParam = Command->Parameters->Add("@RunIDParam", SqlDbType::Int); // ClusteringRunID
		SqlParameter ^ProcessedFlightID = Command->Parameters->Add("@ProcFlightID", SqlDbType::Int); // ProcessedFlightID
	
		RunIDParam->Value = ClusteringRunID; // It is the same for the whole loop
		Command->Prepare();
		for (int i = 0; i < FlightsNum; i++)
		{
			ProcessedFlightID->Value = FlightIDs[i];
			Command->ExecuteNonQuery();
		}

		// Delete (if exist) dublicates of current results
		//Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString();
		//Command->ExecuteNonQuery();

		for (int i = 0; i < FlightsNum; i++)
		{
			Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString() + ", " + Convert::ToString(FlightIDs[i]);
			Command->ExecuteNonQuery();
			InsertClusterLabels(FlightIDs[i], Labels[i], ClusterIDs); // Inserting labels into VectorCluster table
		}
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		delete[] ClusterIDs;
		throw(Exception);
	}
	
	Command->Connection->Close();
	delete[] ClusterIDs;
}

void DBWriter::UpdateClusters (int *FlightIDs, int FlightsNum, int ClustersNum, char *Date, double **Labels,
	double *ClusterParams, int ParamsNum)
{
	// FlightIDs -- array of processed flight IDs
	// FlightsNum -- number of IDs
	// ClustersNum -- number of obtained clusters
	// Labels -- 2D array of cluster labels for each vector for each flight from FlightIDs
	// ClusterParams -- parameters of the clustering
	// ParamsNum -- length of ClusterParams (in doubles!)
	String ^RunDate = gcnew String(Date);
	
	int ClusteringRunID;
	int *ClusterIDs = new int[ClustersNum];
	Int32 ^ClNum = ClustersNum;

	System::IO::StreamWriter ^Log = gcnew System::IO::StreamWriter("writerlog.txt", true);

	Log->WriteLine(System::DateTime::Now + " DBWriter::UpdateClusters message.");
	Log->WriteLine(RunDate);
	Log->WriteLine("ClustersNum = {0}", ClustersNum);
	Log->WriteLine("FlightsNum = {0}", FlightsNum);
	for (int i = 0; i < FlightsNum; ++i)
	{
		Log->Write("{0} ", FlightIDs[i]);
	}
	Log->WriteLine("");
	
	Log->Close();

	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);

		// Saving current clustering run
		Command->CommandText = "SELECT Id FROM ClusteringRun WHERE RunDate = '" + RunDate + "'";
		Read(Command, &ClusteringRunID); // Getting it's ID

		Int32 ^ClustNum;
		Int32 ^ClustRunId = ClusteringRunID; // Adding clusters into cluster table
		for (int i = 0; i < ClustersNum; ++i)
		{
			ClustNum = i + 1;
			Command->CommandText = "EXECUTE SaveCluster @Number = " + ClustNum->ToString() + ", @ClusteringRunId = " +
				ClustRunId->ToString();
			Read(Command, &ClusterIDs[i]); // And getting their IDs.
		}

		// Inserting parameters
		array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(ClusterParams, ParamsNum); // Converting double array to byte array
		// Saving clustering params
		Command->CommandText = "UPDATE ClusterParam SET ClustParams = @ClusterDataParam WHERE ClustRunId = @RunIdParam";
		Command->Parameters->AddWithValue("@RunIdParam", ClusteringRunID);
		Command->Parameters->AddWithValue("@ClusterDataParam", ParamData);
		Command->ExecuteNonQuery();

		// Insert flight clusterings
		Command->Parameters->Clear();
		Command->CommandText = "EXECUTE NewFlightClustering @RunIDParam, @ProcFlightID";
		SqlParameter ^RunIDParam = Command->Parameters->Add("@RunIDParam", SqlDbType::Int); // ClusteringRunID
		SqlParameter ^ProcessedFlightID = Command->Parameters->Add("@ProcFlightID", SqlDbType::Int); // ProcessedFlightID
	
		RunIDParam->Value = ClusteringRunID; // It is the same for the whole loop
		Command->Prepare();
		for (int i = 0; i < FlightsNum; i++)
		{
			ProcessedFlightID->Value = FlightIDs[i];
			Command->ExecuteNonQuery();
		}

		// Delete (if exist) dublicates of current results
		//Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString();
		//Command->ExecuteNonQuery();

		for (int i = 0; i < FlightsNum; i++)
		{
			Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString() + ", " + Convert::ToString(FlightIDs[i]);
			Command->ExecuteNonQuery();
			InsertClusterLabels(FlightIDs[i], Labels[i], ClusterIDs); // Inserting labels into VectorCluster table
		}
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		delete[] ClusterIDs;
		throw(Exception);
	}
	
	Command->Connection->Close();
	delete[] ClusterIDs;
}

void DBWriter::UpdateClusters (int *FlightIDs, int FlightsNum, int ClustersNum, char *Date, double **Labels,
	double *ClusterParams, int ParamsNum, double *UsedParametersNames, int UsedParamsNum)
{
	// FlightIDs -- array of processed flight IDs
	// FlightsNum -- number of IDs
	// ClustersNum -- number of obtained clusters
	// Labels -- 2D array of cluster labels for each vector for each flight from FlightIDs
	// ClusterParams -- parameters of the clustering
	// ParamsNum -- length of ClusterParams (in doubles!)
	String ^RunDate = gcnew String(Date);
	
	int ClusteringRunID;
	int *ClusterIDs = new int[ClustersNum];
	Int32 ^ClNum = ClustersNum;

	System::IO::StreamWriter ^Log = gcnew System::IO::StreamWriter("writerlog.txt", true);

	Log->WriteLine(System::DateTime::Now + " DBWriter::UpdateClusters message.");
	Log->WriteLine(RunDate);
	Log->WriteLine("ClustersNum = {0}", ClustersNum);
	Log->WriteLine("FlightsNum = {0}", FlightsNum);
	for (int i = 0; i < FlightsNum; ++i)
	{
		Log->Write("{0} ", FlightIDs[i]);
	}
	Log->WriteLine("");
	
	Log->Close();

	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);

		// Saving current clustering run
		Command->CommandText = "SELECT Id FROM ClusteringRun WHERE RunDate = '" + RunDate + "'";
		Read(Command, &ClusteringRunID); // Getting it's ID

		Int32 ^ClustNum;
		Int32 ^ClustRunId = ClusteringRunID; // Adding clusters into cluster table
		for (int i = 0; i < ClustersNum; ++i)
		{
			ClustNum = i + 1;
			Command->CommandText = "EXECUTE SaveCluster @Number = " + ClustNum->ToString() + ", @ClusteringRunId = " +
				ClustRunId->ToString();
			Read(Command, &ClusterIDs[i]); // And getting their IDs.
		}

		// Inserting parameters
		array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(ClusterParams, ParamsNum); // Converting double array to byte array
		array<System::Byte> ^UsedParamNamesData = ConvertDoubleArrayToByteArray(UsedParametersNames, UsedParamsNum);
		// Saving clustering params
		Command->CommandText = "UPDATE ClusterParam SET ClustParams = @ClusterDataParam, ParamsUsed = @UsedParametersNames "
			"WHERE ClustRunId = @RunIdParam";
		Command->Parameters->AddWithValue("@RunIdParam", ClusteringRunID);
		Command->Parameters->AddWithValue("@ClusterDataParam", ParamData);
		Command->Parameters->AddWithValue("@UsedParametersNames", UsedParamNamesData);
		Command->ExecuteNonQuery();

		// Insert flight clusterings
		Command->Parameters->Clear();
		Command->CommandText = "EXECUTE NewFlightClustering @RunIDParam, @ProcFlightID";
		SqlParameter ^RunIDParam = Command->Parameters->Add("@RunIDParam", SqlDbType::Int); // ClusteringRunID
		SqlParameter ^ProcessedFlightID = Command->Parameters->Add("@ProcFlightID", SqlDbType::Int); // ProcessedFlightID
	
		RunIDParam->Value = ClusteringRunID; // It is the same for the whole loop
		Command->Prepare();
		for (int i = 0; i < FlightsNum; i++)
		{
			ProcessedFlightID->Value = FlightIDs[i];
			Command->ExecuteNonQuery();
		}

		// Delete (if exist) dublicates of current results
		//Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString();
		//Command->ExecuteNonQuery();

		for (int i = 0; i < FlightsNum; i++)
		{
			Command->CommandText = "EXECUTE DeleteOldVectors " + ClustRunId->ToString() + ", " + Convert::ToString(FlightIDs[i]);
			Command->ExecuteNonQuery();
			InsertClusterLabels(FlightIDs[i], Labels[i], ClusterIDs); // Inserting labels into VectorCluster table
		}
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		delete[] ClusterIDs;
		throw(Exception);
	}
	
	Command->Connection->Close();
	delete[] ClusterIDs;
}

void DBWriter::InsertClusterLabels(Int32 ^FlightID, double *Labels, int *ClustIDs)
{
	int FlightVecNum = 0;
	int *FlightVec = NULL;
	double *ClIDs = NULL, *Vectors = NULL;

	SqlCommand ^Command = gcnew SqlCommand();
	SqlDataReader ^Reader;
	
	try
	{
		Connect(Command);
		
		// How much we are going to insert?
		Command->CommandText = "SELECT COUNT(*) FROM RegVec WHERE(RegVec.ProcessedFlightId = " + FlightID->ToString() + ")";
		Read(Command, &FlightVecNum);

		FlightVec = new int[FlightVecNum];
		// Getting vector IDs, ordered by tact!
		Command->CommandText = "SELECT Id FROM RegVec WHERE(RegVec.ProcessedFlightId = " + FlightID->ToString() + ") ORDER BY Tact";

		Reader = Command->ExecuteReader();

		for (int i = 0; i < FlightVecNum; i++)
		{
			if (Reader->Read())
			{
				FlightVec[i] = Reader->GetInt32(0);
			}
		}
		Reader->Close();

		ClIDs = new double[FlightVecNum];
		Vectors = new double[FlightVecNum];

		for (int i = 0; i < FlightVecNum; ++i)
		{
			Vectors[i] = FlightVec[i];
			ClIDs[i] = ClustIDs[((int)Labels[i]) - 1];
		}

		array<System::Byte> ^VectorIDs = ConvertDoubleArrayToByte4Array(Vectors, FlightVecNum); // Converting double array to byte array
		array<System::Byte> ^ClustNumbers = ConvertDoubleArrayToByte4Array(Labels, FlightVecNum); // Converting double array to byte array
		array<System::Byte> ^ClusterIDs = ConvertDoubleArrayToByte4Array(ClIDs, FlightVecNum); // Converting double array to byte array

		Command->CommandText = "EXECUTE NewVectorClustering @VectorIDs, @ClustNumbers, @ClustIDs, @Size, @Length";
		Command->Parameters->AddWithValue("@VectorIDs", VectorIDs);
		Command->Parameters->AddWithValue("@ClustNumbers", ClustNumbers);
		Command->Parameters->AddWithValue("@ClustIDs", ClusterIDs);
		Command->Parameters->AddWithValue("@Size", int(sizeof(int)));
		Command->Parameters->AddWithValue("@Length", int(sizeof(int) * FlightVecNum));
		Command->ExecuteNonQuery();
	}
	catch (System::Exception ^Exception)
	{
		Reader->Close();
		Command->Connection->Close();
		delete[] FlightVec;
		delete[] ClIDs;
		delete[] Vectors;
		throw(Exception);
	}
	
	Command->Connection->Close();
	delete[] FlightVec;
	delete[] ClIDs;
	delete[] Vectors;
}

int DBWriter::SaveMetricRealization (char *MetricType, char *Date, double *Params, int ParamsNum, char *Note)
{
	int MetricRealizationID;
	
	String ^Type = gcnew String(MetricType);
	String ^RunDate = gcnew String(Date);
	String ^Comment = gcnew String(Note);
	array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(Params, ParamsNum); // Converting double array to byte array
	
	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);
		
		Command->CommandText = "EXECUTE SaveMetricRealization @Date, @Type, @Params, @Note";
		Command->Parameters->AddWithValue("@Date", RunDate);
		Command->Parameters->AddWithValue("@Type", Type);
		Command->Parameters->AddWithValue("@Params", ParamData);
		Command->Parameters->AddWithValue("@Note", Comment);
		Read(Command, &MetricRealizationID);
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();

	return MetricRealizationID;
}

int DBWriter::SaveMetricRealization (char *MetricType, char *Date, double *Params, int ParamsNum,
	double *UsedParametersNames, int UsedParamsNum, char *Note)
{
	int MetricRealizationID;
	
	String ^Type = gcnew String(MetricType);
	String ^RunDate = gcnew String(Date);
	String ^Comment = gcnew String(Note);
	array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(Params, ParamsNum); // Converting double array to byte array
	array<System::Byte> ^UsedParamNamesData = ConvertDoubleArrayToByteArray(UsedParametersNames, UsedParamsNum);
	
	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);

		Command->CommandText = "EXECUTE SaveMetricRealization @Date, @Type, @Params, @Note, @UsedParametersNames";
		Command->Parameters->AddWithValue("@Date", RunDate);
		Command->Parameters->AddWithValue("@Type", Type);
		Command->Parameters->AddWithValue("@Params", ParamData);
		Command->Parameters->AddWithValue("@UsedParametersNames", UsedParamNamesData);
		Command->Parameters->AddWithValue("@Note", Comment);
		Read(Command, &MetricRealizationID);
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();

	return MetricRealizationID;
}

int DBWriter::UpdateMetricRealization (int MetricRealizationID, double *Params, int ParamsNum)
{
	array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(Params, ParamsNum); // Converting double array to byte array
	
	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);

		Command->CommandText = "UPDATE MetricRealization SET MetricParam = @Params WHERE Id = @MetricRealizationID";
		Command->Parameters->AddWithValue("@Params", ParamData);
		Command->Parameters->AddWithValue("@MetricRealizationID", MetricRealizationID);
		Command->ExecuteNonQuery();
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();

	return MetricRealizationID;
}

int DBWriter::UpdateMetricRealization (int MetricRealizationID, double *Params, int ParamsNum,
	double *UsedParametersNames, int UsedParamsNum)
{
	array<System::Byte> ^ParamData = ConvertDoubleArrayToByteArray(Params, ParamsNum); // Converting double array to byte array
	array<System::Byte> ^UsedParamNamesData = ConvertDoubleArrayToByteArray(UsedParametersNames, UsedParamsNum);
	
	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);

		Command->CommandText = "UPDATE MetricRealization SET MetricParam = @Params, ParamsUsed = @UsedParametersNames "
			"WHERE Id = @MetricRealizationID";
		Command->Parameters->AddWithValue("@Params", ParamData);
		Command->Parameters->AddWithValue("@MetricRealizationID", MetricRealizationID);
		Command->Parameters->AddWithValue("@UsedParametersNames", UsedParamNamesData);
		Command->ExecuteNonQuery();
	}
	catch(System::Exception ^Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();

	return MetricRealizationID;
}

int DBWriter::SaveMetric (int MetricRealizationID, int FlightID, double *Values, char *Type, int ValuesNum)
{
	int Result;
	array<System::Byte> ^ValueData = ConvertDoubleArrayToByteArray(Values, ValuesNum); // Converting double array to byte array
	String ^MetricType = gcnew String(Type);

	SqlCommand ^Command = gcnew SqlCommand();

	try
	{
		Connect(Command);

		Command->CommandText = "EXECUTE SaveMetric @RealizationID, @FlightID, @Values, @Type";
		Command->Parameters->AddWithValue("@RealizationID", MetricRealizationID);
		Command->Parameters->AddWithValue("@FlightID", FlightID);
		Command->Parameters->AddWithValue("@Values", ValueData);
		Command->Parameters->AddWithValue("@Type", MetricType);
		Read(Command, &Result);
	}
	catch(System::Exception ^ Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();

	return Result;
}

array<System::Byte> ^DBWriter::ConvertDoubleArrayToByteArray(double *data, int size)
{
	array<System::Byte> ^Buffer = gcnew array<System::Byte>(size * sizeof(double));
	array<System::Byte> ^tmp;

	for (int i = 0; i < size; i++)
	{
		tmp = BitConverter::GetBytes(data[i]);
		for (int j = 0; j < sizeof(double); j++)
		{
			Buffer[sizeof(double)*i + j] = tmp[j];
		}
	}
	return Buffer;
}

array<System::Byte> ^DBWriter::ConvertDoubleArrayToByte4Array(double *data, int size)
{
	array<System::Byte> ^Buffer = gcnew array<System::Byte>(size * sizeof(int));
	array<System::Byte> ^tmp;

	for (int i = 0; i < size; i++)
	{
		tmp = BitConverter::GetBytes((int)data[i]);
		for (int j = 0; j < sizeof(int); j++)
		{
			Buffer[sizeof(int)*i + j] = tmp[sizeof(int) - j - 1];
		}
	}
	return Buffer;
}

int DBWriter::InsertNewFlight(char* FlightName, char* PlaneName, char* StartDateTime, char* StopDateTime, int* PlaneId)
{
	String^ FlightNm = gcnew String(FlightName);
	String^ PlaneNm = gcnew String(PlaneName);
	String^ StartDT = gcnew String(StartDateTime);
	String^ StopDT = gcnew String(StopDateTime);
	int FlightId = -1;
	
	SqlCommand ^Command = gcnew SqlCommand();
	try
	{
		Connect(Command);
		if( (StartDT == nullptr) || (StopDT == nullptr) )
		{
			Command->CommandText = "EXECUTE InsertNewFlight @FlightName, @PlaneName";
			Command->Parameters->AddWithValue("@FlightName", FlightNm);
			Command->Parameters->AddWithValue("@PlaneName", PlaneNm);
		}
		else
		{
			Command->CommandText = "EXECUTE InsertNewFlight @FlightName, @PlaneName, @StartDateTime, @StopDateTime";
			Command->Parameters->AddWithValue("@FlightName", FlightNm);
			Command->Parameters->AddWithValue("@PlaneName", PlaneNm);
			Command->Parameters->AddWithValue("@StartDateTime", StartDT);
			Command->Parameters->AddWithValue("@StopDateTime", StopDT);
		}
		//Read(Command, &FlightId);
		SqlDataReader ^Reader;
		Reader = Command->ExecuteReader();
		if (Reader->Read())
		{
			FlightId = Reader->GetInt32(0);
			*PlaneId = Reader->GetInt32(1);
		}
		else
		{
			FlightId = -1;
			*PlaneId = -1;
		}
		Reader->Close();
	}
	catch(System::Exception ^ Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();

	return FlightId;
}

void DBWriter::RegisterVectors(int ProcessedFlightID, int Freq, int TactsNum)
{	
	SqlCommand ^Command = gcnew SqlCommand();
	try
	{
		Connect(Command);
		
		Command->CommandText = "EXECUTE InsertRegVecs @ProcessedFlightID, @Freq, @TactsNum";
		Command->Parameters->AddWithValue("@ProcessedFlightID", ProcessedFlightID);
		Command->Parameters->AddWithValue("@Freq", Freq);
		Command->Parameters->AddWithValue("@TactsNum", TactsNum);

		Command->ExecuteNonQuery();
	}
	catch(System::Exception ^ Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();
}

void DBWriter::SaveXMLBlank(int MetricRealizationID, int FlightID, char *cXMLFile)
{
	SqlCommand ^Command = gcnew SqlCommand();
	try
	{
		String ^sXMLPath = gcnew String(cXMLFile);
		Connect(Command);
		
		Command->CommandText = "EXECUTE SaveXMLBlank @MetricRealizationID, @FlightID, @xmlData";
		Command->Parameters->Add("@xmlData", SqlDbType::Xml);

        XmlReader ^xr = XmlReader::Create(sXMLPath);
        Command->Parameters[0]->Value = gcnew SqlXml(xr);

		Command->Parameters->AddWithValue("@MetricRealizationID", MetricRealizationID);
		Command->Parameters->AddWithValue("@FlightID", FlightID);

		Command->ExecuteNonQuery();
	}
	catch(System::Exception ^ Exception)
	{
		Command->Connection->Close();
		throw(Exception);
	}

	Command->Connection->Close();
}